from BPR.Recommender import Recommender
from BPR.DataLoader import DataLoader
from RecommendManager import RecommendManager
from BookManager import BookManager
from InteractionManager import InteractionManager
from RegisterManager import RegisterManager
from ShelfManager import ShelfManager
from flask import Flask, jsonify, request, render_template
from LoginManager import LoginManager
from UserManager import UserManager
from LoginManager import log_output
import json
app = Flask(__name__, static_url_path='/assets',
            static_folder='./assets/', template_folder='web/')


# Hyper Params for Recommender
hyper_params = {
    'dataset_path': 'BPR/datasets/lib.txt',
    'database_path': 'database/interact_data.db',
    'batch_size': 32,
    'epochs': 5,
    'embed_dim': 32,
    'apply_weight': True,
    'neg_sample_cnt': 200,
    'epsilon': 0.1,
    'extra_dim': 4,
    'apply_extra': True,
    'extra_weight': 0.01,
    'coarse_count': 500
}

# Initializing Managers
print('Server initializing...')
user_manager = UserManager()
login_manager = LoginManager(user_manager)
register_manager = RegisterManager(user_manager)
interaction_manager = InteractionManager(user_manager)
book_manager = BookManager()
shelf_manager = ShelfManager(user_manager, book_manager)
recommender = Recommender(hyper_params)
recommend_manager = RecommendManager(user_manager, book_manager, recommender)
data_loader = DataLoader(hyper_params)
print('Finished.')


# Root Path is Not Used
@app.route('/', methods=['GET'])
def root_not_found():
    log_output('Root Visit', print_to_screen=False)
    try:
        token = request.args.get('token', type=str)
        book_id = request.args.get('book_id', type=int)
        book_title = book_manager.get_book_info(book_id).title
        user_id = user_manager.get_user_id_with_token(token)
        show_info = data_loader.generate_user_show_info(user_id=user_id)
        return render_template('monitor.html', show_info=show_info[book_id], book_title=book_title)
    except Exception as err:
        log_output(str(err))
        return jsonify({'error': 'Token or Book ID not correct.'})


# Login
@app.route('/login', methods=['POST', 'GET'])
def app_login():
    log_output('Login Visit', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = login_manager.login(send_data)
        return jsonify(result)
    except Exception as err:
        print(err)
        # Login Error
        return jsonify(login_manager.error_info)


# Register
@app.route('/register', methods=['POST', 'GET'])
def app_register():
    log_output('Register Visit', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = register_manager.register(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        # Login Error
        return jsonify(register_manager.error_info)


# Sent Interaction Data
@app.route('/interaction', methods=['POST', 'GET'])
def send_interaction_data():
    log_output('Send Interaction Data', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        interaction_manager.send_interaction(send_data)
        return jsonify({'type': 0})
    except Exception as err:
        log_output(str(err))
        return jsonify({'type': 1})


# Return Book Info
@app.route('/bookinfo', methods=['POST', 'GET'])
def get_book_info():
    log_output('Get book info', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = book_manager.request_book_info(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({'type': 1})


# Return Book Text
@app.route('/booktext', methods=['POST', 'GET'])
def get_book_text():
    log_output('Get book text', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = book_manager.request_chapter_text(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({'type': 1})


# Return Book Search
@app.route('/booksearch', methods=['POST', 'GET'])
def get_book_search():
    log_output('Get book search', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = book_manager.request_search(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({"ok": False})


# Return Special Search
@app.route('/specialsearch', methods=['POST', 'GET'])
def get_special_search():
    log_output('Get special book search', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = book_manager.request_special_search(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({"ok": False})


# Return Shelf
@app.route('/shelf', methods=['POST', 'GET'])
def get_shelf():
    log_output('Get shelf', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = shelf_manager.request_shelf(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify(shelf_manager.error_info)


# Return Hot Books
@app.route('/hotbook', methods=['POST', 'GET'])
def get_hot_book():
    log_output('Get hot books', print_to_screen=False)
    try:
        result = recommend_manager.request_hot_book()
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({'ok': False})


# Return Recommendation
@app.route('/recommendation', methods=['POST', 'GET'])
def get_recommendation():
    log_output('Get recommendation', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = recommend_manager.get_recommendation(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({'ok': False})


# Modify Shelf
@app.route('/modifyshelf', methods=['POST', 'GET'])
def modify_shelf():
    log_output('Modify shelf', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = shelf_manager.modify_shelf(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({'type': 1})

# Modify Shelf


@app.route('/getrate', methods=['POST'])
def get_book_rate():
    log_output('Get book rate', print_to_screen=False)
    try:
        text_data = request.get_data(as_text=True)
        log_output(text_data)
        send_data = json.loads(text_data)
        result = interaction_manager.request_book_rate(send_data)
        return jsonify(result)
    except Exception as err:
        log_output(str(err))
        return jsonify({'ok': False})


if __name__ == '__main__':
    print('Starting server...')
    app.run(host='0.0.0.0', port='6777', debug=True)
